package cz.pecinovsky.česky.oopnz._134_;
//Příliš žluťoučký kůň úpěl ďábelské ódy

import cz.pecinovsky.česky.oopnz.správce.Kreslítko;
import cz.pecinovsky.česky.oopnz.správce.Obdélník;
import cz.pecinovsky.česky.oopnz.správce.SprávcePlátna;


//import static cz.pecinovsky.česky.oopnz._134_.IModulový_134_.IModulový;
import static cz.pecinovsky.česky.oopnz._134_.IOtočný_136_      .IOtočný;
import static cz.pecinovsky.česky.oopnz._134_.Světlo_134_.Světlo;


//import static cz.pecinovsky.česky.oopnz._134_.Auto_134_         .Auto;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ Konec ignorovaného počátečního textu +++++
//%I+ >=132z
//
//import cz.pecinovsky.česky.oopnz.správceplátna.Kreslítko;
//import cz.pecinovsky.česky.oopnz.správceplátna.Obdélník;
//import cz.pecinovsky.česky.oopnz.správceplátna.SprávcePlátna;
//%I-

import cz.pecinovsky.česky.oopnz.utility.Barva;
//%A+ >136
import cz.pecinovsky.česky.oopnz.utility.Oblast;
//%A-
import cz.pecinovsky.česky.oopnz.utility.Pozice;
//%A+ >136
import cz.pecinovsky.česky.oopnz.utility.Směr8;
//%A-
//%X+ xxxxx Začátek přeskakovaného textu xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   oopnz._115_._116_Autor_119
 * Následující: Prozatím není
 *
 * Projekt  026z - Komentáře
 *   + Začlenění do standardní šablony + Komentáře
 *
 * Projekt  021z - Použití this
 *   ~ V prvních dvou konstruktorech nahrazena původní těla
 *     příkazem this volajícím obecnější konstruktor
 *
 * Projekt  022z - Přetěžování
 *   + Přidány další dva konstruktory
 *   ~ Ve třetím konstruktoru nahrazeno tělo příkazem this
 *     volající přidaný obecnější konstruktor
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class Auto_134_
{    private Auto_134_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- Konec přeskakovaného textu -----


/*******************************************************************************
 * Instance třídy {@code Auto} představují auta směřující na východ.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
//%I+ <136
//public class Auto implements IModulový
//%I-
//%A+ >136
public class Auto implements IOtočný
//%A-
     {
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    private static final int IMPLICITNÍ_X = 0;

    private static final int IMPLICITNÍ_Y = 0;

    private static final Barva IMPLICITNÍ_BARVA_PODVOZKU = Barva.MODRÁ;

    private static final Barva BARVA_KABINY = Barva.ŠEDÁ;

    private static final int IMPLICITNÍ_DÉLKA = 128;
//%A+ >136

    private static final Směr8 IMPLICITNÍ_SMĚR = Směr8.VÝCHOD;

    /** Plátno, na které se bude instance kreslit. */
    private static final SprávcePlátna SP = SprávcePlátna.getInstance();
//%A-



//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================

     /** Počet doposud vytvořených instancí. */
     private static int počet = 0;



//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Pořadové (identifikační) číslo dané instance. */
    private final int ID;

    /** Podvozek auta. */
    private final Obdélník podvozek;

    /** Kabina auta. */
    private final Obdélník kabina;

    /** Levé přední světlo. */
    private final Světlo světloL;

    /** Pravé přední světlo. */
    private final Světlo světloP;



//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** Název instance sestávající implicitně z názvu třídy a ID instance */
    private String název;
//%A+ >136

    /** Bodová x-ová souřadnice instance. */
    private int xPos;

    /** Bodová y-ová souřadnice instance. */
    private int yPos;

    /** Velikost strany čverce vyplněného šipkou v bodech. */
    private int modul;

    /** Směr, do nějž je šipka natočena. */
    private Směr8 směr;
//%A-



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří auto implicitních rozměrů a s implicitní barvou podvozku
     * umístěné v levém horním rohu plátna.
     */
    public Auto()
    {
        this(IMPLICITNÍ_X, IMPLICITNÍ_Y);
    }


    /***************************************************************************
     * Vytvoří auto implicitních rozměrů a s implicitní barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     */
    public Auto(int x, int y)
    {
        this(x, y, IMPLICITNÍ_BARVA_PODVOZKU);
    }


    /***************************************************************************
     * Vytvoří auto implicitních rozměrů se zadanou barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param barvaPodvozku  Požadovaná barva podvozku
     */
    public Auto(int x, int y, Barva barvaPodvozku)
    {
        this(x, y, IMPLICITNÍ_DÉLKA, barvaPodvozku);
    }


    /***************************************************************************
     * Vytvoří auto zadané délky s implicitní barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param modul  Délka auta
     */
    public Auto(int x, int y, int modul)
    {
        this(x, y, modul, IMPLICITNÍ_BARVA_PODVOZKU);
    }


    /***************************************************************************
     * Vytvoří auto zadané délky se zadanou barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param modul         Délka auta
     * @param barvaPodvozku Požadovaná barva podvozku
     */
    public Auto(int x, int y, int modul, Barva barvaPodvozku)
    {
//%I+ <136
//        počet   = počet + 1;
//        this.ID = počet;
//
//        int d1 = modul;
//        int d2 = modul/2;
//        int d4 = modul/4;
//        int d8 = modul/8;
//
//        podvozek = new Obdélník(x,    y,    d1, d2, barvaPodvozku);
//        kabina   = new Obdélník(x+d8, y+d8, d2, d4, BARVA_KABINY );
//
//        světloL  = new Světlo(x+7*d8, y,      d8);
//        světloP  = new Světlo(x+7*d8, y+3*d8, d8);
//    }
//%I-
//%A+ >136
        this(x, y, modul, barvaPodvozku, Směr8.VÝCHOD);
    }


    /***************************************************************************
     * Vytvoří auto zadané délky se zadanou barvou podvozku
     * umístěné na zadaných souřadnicích a natočené zadaným směrem;
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param modul Délka auta a současně strana čtverce, v němž bude vystředěno
     * @param barvaPodvozku Požadovaná barva podvozku
     * @param směr  Směr, do nějž bude vytvořené auto natočeno
     */
    public Auto(int x, int y, int modul, Barva barvaPodvozku, Směr8 směr)
    {
        Auto.počet = počet + 1;
        this.ID    = počet;
        
        this.xPos  = x;
        this.yPos  = y;
        this.modul = modul;
        this.směr  = směr;

        int m1 =     modul;
        int m2 =     modul / 2;
        int m4 =     modul / 4;
        int m8 =     modul / 8;
        int m38= 3 * modul / 8;
        int m58= 5 * modul / 8;
        int m78= 7 * modul / 8;

        Oblast ref = new Oblast(x, y, modul, modul);
        Oblast díl;

        //Podvozek
        díl = new Oblast(0, m4, m1, m2);
        díl = směr.otočVOblast(díl, ref);
        this.podvozek = new Obdélník(díl, barvaPodvozku);

        //Kabina
        díl = new Oblast(m8, m38, m2, m4);
        díl = směr.otočVOblast(díl, ref);
        this.kabina = new Obdélník(díl, BARVA_KABINY);

        //světloL
        díl = new Oblast(m78, m4, m8, m8);
        díl = směr.otočVOblast(díl, ref);
        this.světloL = new Světlo(díl.x, díl.y, díl.výška);

        //světloP
        díl = new Oblast(m78, m58, m8, m8);
        díl = směr.otočVOblast(díl, ref);
        this.světloP = new Světlo(díl.x, díl.y, díl.výška);
    }
//%A-



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================

    // Sada přístupových metod vlastnosti: Pozice ******************************

    /***************************************************************************
     * Vrátí x-ovou (vodorovnou) souřadnici pozice instance.
     *
     * @return  x-ová souřadnice.
     */
    public int getX()
    {
//%I+ <136
//        return podvozek.getX();
//%I-
//%A+ >136
        return xPos;
//%A-
    }


    /***************************************************************************
     * Vrátí y-ovou (svislou) souřadnici pozice instance.
     *
     * @return  y-ová souřadnice.
     */
    public int getY()
    {
//%I+ <136
//        return podvozek.getY();
//%I-
//%A+ >136
        return yPos;
//%A-
    }


    /***************************************************************************
     * Vrátí přepravku se svojí aktuální pozicí.
     *
     * @return Aktuální pozice světla
     */
    @Override
    public Pozice getPozice()
    {
        return new Pozice(getX(), getY());
    }


    /***************************************************************************
     * Nastaví novou pozici světla.
     *
     * @param p Nastavovaná pozice
     */
    @Override
    public void setPozice(Pozice p)
    {
        this.setPozice(p.x, p.y);
    }


    /***************************************************************************
     * Nastaví novou pozici instance.
     *
     * @param x   Nová x-ová pozice instance
     * @param y   Nová y-ová pozice instance
     */
    @Override
    public void setPozice(int x, int y)
    {
//%I+ <136
//        int d8 = podvozek.getŠířka() / 8;   //Osmina délky vozu
//
//        podvozek.setPozice(x,      y);
//        kabina  .setPozice(x+d8,   y+d8);
//        světloL .setPozice(x+7*d8, y);
//        světloP .setPozice(x+7*d8, y+3*d8);
//%I-
//%A+ >136
        int dx = x - getX();
        int dy = y - getY();
        SP.nekresli(); {
            podvozek.posunVpravo(dx);       podvozek.posunDolů  (dy);
            kabina  .posunVpravo(dx);       kabina  .posunDolů  (dy);
            světloL .setPozice(světloL.getX()+dx, světloL.getY()+dy);
            světloP .setPozice(světloP.getX()+dx, světloP.getY()+dy);
        } SP.vraťKresli();
        xPos = x;
        yPos = y;
//%A-
    }


    // Sada přístupových metod vlastnosti: Rozměr / Modul **********************

    /***************************************************************************
     * Vrátí základní délku, od níž se odvozují všechny rozměry objektu -
     * pro auto je to jeho délka.
     *
     * @return Délka auta
     */
    @Override
    public int getModul()
    {
//%I+ <136
//        return podvozek.getŠířka();
//%I-
//%A+ >136
        return modul;
//%A-
    }


    /***************************************************************************
     * Nastaví nový základní rozměr instance - novou délku vozu.
     * Ostatní rozměry jsou od ní odvozené.
     *
     * @param modul  Nově nastavovaná délka auta; délka > 0
     */
    @Override
    public void setModul(int modul)
    {
//%A+ >139
        if (modul <= 0) {
            throw new IllegalArgumentException(
                    "\nVelikost modulu musí být nezáporná - zadáno " + modul);
        }
//%A-
        int x  = podvozek.getX();
        int y  = podvozek.getY();
        int m1 = modul;
        int m2 = m1/2;
        int m4 = m1/4;
        int m8 = m1/8;
//%I+ <136
//
//        podvozek.setRozměr(m1, m2);
//
//        //U ostatních částí vozu se se změnou rozměru vozu mění i jejich pozice
//        kabina.setPozice(x+m8, y+m8);
//        kabina.setRozměr(m2, m4);
//
//        světloL.setPozice(x+7*m8, y);
//        světloP.setPozice(x+7*m8, y+3*m8);
//        světloL.setModul(m8);
//        světloP.setModul(m8);
//    }
//
//%I-
//%A+ >136
        int m38= 3 * m1 / 8;
        int m58= 5 * m1 / 8;
        int m78= 7 * m1 / 8;

        Oblast ref = new Oblast(xPos, yPos, modul, modul);
        Oblast díl;

        SP.nekresli(); {
            //Podvozek
            díl = new Oblast(0, m4, m1, m2);
            díl = směr.otočVOblast(díl, ref);
            this.podvozek.setOblast(díl);

            //Kabina
            díl = new Oblast(m8, m38, m2, m4);
            díl = směr.otočVOblast(díl, ref);
            this.kabina.setOblast(díl);

            //světloL
            díl = new Oblast(m78, m4, m8, m8);
            díl = směr.otočVOblast(díl, ref);
            this.světloL.setPozice(díl.x, díl.y);
            this.světloL.setModul(díl.výška);

            //světloP
            díl = new Oblast(m78, m58, m8, m8);
            díl = směr.otočVOblast(díl, ref);
            this.světloP.setPozice(díl.x, díl.y);
            this.světloP.setModul(díl.výška);
        } SP.vraťKresli();
        this.modul = modul;
    }


    /***************************************************************************
     * Vrátí směr, do nějž je šipka natočena.
     *
     * @return Směr, do nějž je šipka natočena
     */
    @Override
    public Směr8 getSměr()
    {
        return směr;
    }


    /***************************************************************************
     * Natočí šipku do zadaného směru.
     *
     * @param směr  Směr, do nějž se má šipka natočit
     */
    @Override
    public void setSměr(Směr8 směr)
    {
//%A-
//%A+ >139
        if (! směr.isHlavní()) {
            throw new IllegalArgumentException(
                "\nNebyl zadán hlavní směr - zadáno " + směr);
        }
//%A-
//%A+ >136
        this.směr = směr;
        this.setModul(modul);
    }

//%A-


//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================

    /***************************************************************************
     * Blikne světly na levé straně auta.
     */
    public void blikniVlevo()
    {
        světloL.blikni();
    }


    /***************************************************************************
     * Blikne světly na pravé straně auta.
     */
    public void blikniVpravo()
    {
        světloP.blikni();
    }


    /***************************************************************************
     * Prostřednictvím dodaného kreslítka vykreslí obraz své instance.
     *
     * @param kreslítko Kreslítko, které nakreslí instanci
     */
    @Override
    public void nakresli(Kreslítko kreslítko)
    {
        podvozek.nakresli(kreslítko);
        kabina  .nakresli(kreslítko);
        světloL .nakresli(kreslítko);
        světloP .nakresli(kreslítko);
    }


    /***************************************************************************
     * Zhasne všechna světla auta.
     */
    public void rozsviť()
    {
        světloL.rozsviť();
        světloP.rozsviť();
    }


    /***************************************************************************
     * Zhasne všechna světla auta.
     */
    public void zhasni()
    {
        světloL.zhasni();
        světloP.zhasni();
    }


    /***************************************************************************
     * Vrací textovou reprezentaci (podpis) dané instance
     * používanou především k ladicím účelům.
     *
     * @return Požadovaná textová reprezentace
     */
    @Override
    public String toString()
    {
        return "Auto_" + ID + "(" + getPozice() + ", modul=" + getModul() +
               ", barva=" + podvozek.getBarva() + ")";
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTY A METODA MAIN =======================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        Světlo inst = new Světlo();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}

//%%-  ----- Začátek ignorovaného závěrečného textu -----
////////////////////////////////////////////////////////////////////////////////

//== TESTY A METODA MAIN =======================================================

    /***************************************************************************
     * Testovací metoda.
     */
    public static void test()
    {
//        new Auto();
//        new Auto(100, 100);
//        new Auto( 50, 200, Barva.ČERNÁ);

        //023
        SprávcePlátna SP = SprávcePlátna.getInstance();
        SP.setKrokRozměr(25, 10, 6);
        SP.setNázev("Auto v souřadné mřížce");
        Auto a = new Auto(25, 25, 200);
        SP.přidej(a);
//        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main( String[] args )  {  test();  }
}
